package com.st.springbootwebsocket;

import cn.hutool.json.JSONUtil;
import jakarta.websocket.OnClose;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

/**
 * WebSocket类，用于处理WebSocket连接
 * 通过@ServerEndpoint注解来声明这是一个WebSocket的端点
 * 通过@Component注解将其标记为Spring的一个组件，以便自动扫描和管理
 */
@ServerEndpoint(value = "/websocket/{userId}")
@Component
public class WebSocket {
    /**
     * 实例一个session，这个session是websocket的session
     */
    private Session session;

    /**
     * 用于存放所有在线用户的websocket
     */
    private static ConcurrentHashMap<String, WebSocket> webSocketMap = new ConcurrentHashMap<>();

    /**
     * 获取WebSocket实例映射
     *
     * @return WebSocket实例映射
     */
    public static ConcurrentHashMap<String, WebSocket> getWebSocketMap() {
        return webSocketMap;
    }

    /**
     * 设置WebSocket实例映射
     *
     * @param webSocketMap WebSocket实例映射
     */
    public static void setWebSocketMap(ConcurrentHashMap<String, WebSocket> webSocketMap) {
        WebSocket.webSocketMap = webSocketMap;
    }

    /**
     * 主动向客户端发送消息的方法
     *
     * @param message 消息内容
     * @param userId  用户ID
     */
    public static void sendMessage(Object message, String userId) {
        WebSocket webSocket = webSocketMap.get(userId);
        if (webSocket != null) {
            try {
                webSocket.session.getBasicRemote().sendText(JSONUtil.toJsonStr(message));
                System.out.println("【websocket消息】发送消息成功,用户=" + userId + ",消息内容" + message.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 1、当新的WebSocket连接打开时调用的方法
     *
     * @param session 当前会话
     * @param userId  用户ID
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        this.session = session;
        webSocketMap.put(userId, this);
        sendMessage("CONNECT_SUCCESS", userId);
        System.out.println("【websocket消息】有新的连接,连接id" + userId);
    }

    /**
     * 3、当WebSocket连接关闭时调用的方法
     *
     * @param userId 用户ID
     */
    @OnClose
    public void onClose(@PathParam("userId") String userId) {
        webSocketMap.remove(userId);
        System.out.println("【websocket消息】连接断开,总数:" + webSocketMap.size());
    }

    /**
     * 2、当接收到客户端发送的消息时调用的方法
     *
     * @param message 消息内容
     */
    @OnMessage
    public void onMessage(String message) {
        if (!message.equals("ping")) {
            System.out.println("【websocket消息】收到客户端发来的消息:" + message);
        }
    }
}
